package com.zhuss.core.processor;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import com.zhuss.bean.bo.core.resource.SearchResourceBo;
import com.zhuss.bean.bo.core.upload.DownloadBo;
import com.zhuss.bean.vo.core.resource.DetailResourceVo;
import com.zhuss.bean.vo.core.resource.ListMenuTreeVo;
import com.zhuss.bean.vo.core.resource.ListResourceTreeVo;
import com.zhuss.bean.vo.core.resource.ListResourceVo;
import com.zhuss.bean.vo.core.upload.DownloadVo;
import com.zhuss.common.PageVo;
import com.zhuss.common.Processor;
import com.zhuss.core.db.dao.ext.ResourceDao;
import com.zhuss.core.db.entity.Resource;
import com.zhuss.enums.IsEnum;
import com.zhuss.enums.ResourceType;
import com.zhuss.exception.OceanException;
import com.zhuss.exception.ExceptionCode;
import com.zhuss.util.ListBean;

/**
 * 查询菜单资源 processor
 * @Author: zhushanshuo
 * @Date: 2019/9/24 19:54
 */
@Component("resourceRead")
public class ResourceRead {
	
	@Autowired
	private ResourceDao resourceDao;
	
	@Autowired
	@Qualifier("downloadProcessor")
	private Processor<DownloadVo, DownloadBo> downloadProcessor;
	
	
	/**
	 * 接口
	 * @param system
	 * @return
	 */
	public Object listResource(List<Long> resourceIdList) {
		List<Resource> result = resourceDao.listByIdList(ResourceType.资源点.key(), resourceIdList);
		return result;
	}
	
	
	/**
	 * 菜单
	 * @param system
	 * @return
	 */
	public Object listMenu(List<Long> resourceIdList) {
		List<Resource> result = resourceDao.listByIdList(ResourceType.菜单.key(), resourceIdList);
		return result;
	}
	
	
	/**
	 * 公共接口
	 * @param system
	 * @return
	 */
	public Object listResourcePublic(Integer system) {
		List<Resource> menuList = resourceDao.listAll(ResourceType.资源点.key(), system, IsEnum.是.key());
		List<Long> result = new ArrayList<Long>();
		transferToListId(menuList, result);
		return result;
	}
	
	/**
	 * 公共菜单ID
	 * @param system
	 * @return
	 */
	public Object listMenuPublic(Integer system) {
		List<Long> result = resourceDao.listAllId(ResourceType.菜单.key(), system, IsEnum.是.key());
		return result;
	}
	
	/**
	 * 子级菜单ID
	 * @param system
	 * @param parent
	 * @return
	 */
	public Object listMenuIdByParent(Integer system, Long parent) {
		List<Long> result = resourceDao.listByParentId(ResourceType.菜单.key(), system, parent);
		return result;
	}
	
	/**
	 * 子级菜单
	 * @param system
	 * @param parent
	 * @return
	 */
	public Object listMenuIdByParent(Integer system, List<Long> parentList) {
		List<Long> result = resourceDao.listByParentList(ResourceType.菜单.key(), system, parentList);
		return result;
	}
	
	
	/**
	 * 接口(区分系统)
	 * @param system
	 * @return
	 */
	public Object listResourceId(Integer system) {
		List<Resource> menuList = resourceDao.listAll(ResourceType.资源点.key(), system, null);
		List<Long> result = new ArrayList<Long>();
		transferToListId(menuList, result);
		return result;
	}
	
	
	/**
	 * 菜单(区分系统)
	 * @param system
	 * @return
	 */
	public Object listMenuId(Integer system) {
		List<Resource> menuList = resourceDao.listAll(ResourceType.菜单.key(), system, null);
		List<Long> result = new ArrayList<Long>();
		transferToListId(menuList, result);
		return result;
	}
	
	/**
	 * 菜单(区分系统)
	 * @param system
	 * @return
	 */
	public List<Resource> listMenuByParent(Integer system, Long parent) {
		List<Resource> result = resourceDao.listByParent(ResourceType.菜单.key(), system, parent);
		return result;
	}
	
	/**
	 * 菜单(区分系统)ID
	 * @param system
	 * @return
	 */
	public Object listMenuIdShow(Integer system) {
		List<Long> result = resourceDao.listAllShow(ResourceType.菜单.key(), system, null, IsEnum.是.key());
		return result;
	}
	
	private void transferToListId(List<Resource> menuList, List<Long> result) {
		for (Resource item : menuList) {
			result.add(item.getResourceId());
		}
		
	}

	/**
	 * 菜单树
	 * @param system
	 * @return
	 */
	public Object listMenuTree(Integer system) {
		List<Resource> menuList = resourceDao.listAll(ResourceType.菜单.key(), system, null);
		List<ListMenuTreeVo> result = new ArrayList<>();
		transferTree(menuList, result);
		return result;
	}
	
	/**
	 * 转换菜单树
	 * @param menuList
	 * @param result
	 */
	private void transferTree(List<Resource> menuList, List<ListMenuTreeVo> result) {
		for (Resource menu : menuList) {
			if (menu.getParent() == null || menu.getParent().equals(0l)) {
				ListMenuTreeVo vo = new ListMenuTreeVo();
				vo.setLabel(menu.getName());
				vo.setValue(menu.getResourceId());
				vo.setUrl(menu.getUrl());
				result.add(vo);
			}
		}
		
		for (ListMenuTreeVo vo : result) {
			vo.setChildren(init(menuList, vo));
		}
	}
	
	/**
	 * 递归初始化菜单树
	 * @param menuList
	 * @param vo
	 * @return
	 */
	private List<ListMenuTreeVo> init(List<Resource> menuList, ListMenuTreeVo vo) {
		ListBean<ListMenuTreeVo> listBean = new ListBean<>();
		for (Resource menu : menuList) {
			if (vo.getValue().equals(menu.getParent())) {
				ListMenuTreeVo item = new ListMenuTreeVo();
				item.setValue(menu.getResourceId());
				item.setLabel(menu.getName());
				item.setUrl(menu.getUrl());
				item.setChildren(init(menuList, item));
				listBean.build(item);
			}
		}
		return listBean.getList();
	}
	
	/**
	 * 查询菜单资源列表
	 * @param bo
	 * @return
	 * @throws OceanException
	 */
	public Object list(SearchResourceBo bo) throws OceanException {
		PageVo<ListResourceVo> result = new PageVo<ListResourceVo>();
        result.setPageNum(bo.getPageNum());
        result.setPageSize(bo.getPageSize());
        result.setItems(transferToList(resourceDao.list(bo)));
        result.setTotal(resourceDao.countList(bo));
		return result;
	}
	
	/**
	 * 转换菜单资源列表
	 * @param list
	 * @return
	 * @throws OceanException
	 */
	private List<ListResourceVo> transferToList(List<ListResourceVo> list) throws OceanException {
		for (ListResourceVo item : list) {
			Long parent = item.getParent();
			if (parent == null || parent.equals(0l)) {
				item.setParentName("");
				continue;
			}
			item.setParentName(((DetailResourceVo) detail(parent)).getName());
		}
		return list;
	}
	
	/**
	 * 查询菜单资源详情
	 * @param resourceId
	 * @return
	 * @throws OceanException
	 */
	public Object detail(Long resourceId) throws OceanException {
		Object result = resourceDao.detail(resourceId);
		if (result == null) {
			throw new OceanException(ExceptionCode.数据不存在);
		}
		List<Long> parentList = new ArrayList<Long>();
		listParent(resourceId, parentList);
		DetailResourceVo vo = ((DetailResourceVo) result);
		vo.setParentList(parentList);
		DownloadBo downloadBo = new DownloadBo();
		downloadBo.setKey(vo.getImg());
		DownloadVo downloadVo = downloadProcessor.process(downloadBo);
		vo.setImgUrl(downloadVo.getUrl());
		
		downloadBo = new DownloadBo();
		downloadBo.setKey(vo.getDisImg());
		downloadVo = downloadProcessor.process(downloadBo);
		vo.setDisImgUrl(downloadVo.getUrl());
		return result;
	}
	
	/**
	 * 查询菜单资源所有父级
	 * @param resourceId
	 * @param parentList
	 */
	public void listParent(Long resourceId, List<Long> parentList) {
		Long parent = resourceDao.listParent(resourceId);
		if (parent != null && !parent.equals(0l)) {
			parentList.add(parent);
			listParent(parent, parentList);
		}
		return;
	}
	
	/**
	 * 查询菜单资源子集
	 * @param resourceId
	 * @return
	 */
	public List<Resource> listSon(Long resourceId) {
		List<Resource> result = resourceDao.listSon(resourceId);
		return result;
	}
	
	/**
	 * 查询菜单和资源的混合树 
	 * @param system
	 * @return
	 */
	public Object listResourceTree(Integer system) {
		List<Resource> menuList = resourceDao.listAll(null, system, null);
		List<ListResourceTreeVo> result = new ArrayList<>();
		transferResourceTree(menuList, result);
		return result;
	}
	
	/**
	 * 查询菜单和资源的混合树 
	 * @param system
	 * @return
	 */
	public Object listResourceTreeNoPublic(List<Integer> systemList) {
		List<Resource> menuList = new ArrayList<Resource>();
		for (Integer system : systemList) {
			List<Resource> list = resourceDao.listAll(null, system, IsEnum.否.key());
			menuList.addAll(list);
		}
		List<ListResourceTreeVo> result = new ArrayList<>();
		transferResourceTree(menuList, result);
		return result;
	}
	
	/**
	 * 根据名字查询资源
	 * @param 
	 * @return
	 */
	public List<Resource> list(String name, Integer system) {
		List<Resource> result = resourceDao.listByNameAndSystem(name, system);
		return result;
	}
	
	public List<Resource> listNotId(String name, Long resourceId, Integer system) {
		List<Resource> result = new ArrayList<Resource>();
		List<Resource> list = list(name, system);
		for (Resource c : list) {
			if (!c.getResourceId().equals(resourceId)) {
				result.add(c);
				break;
			}
		}
		return result;
	}
	
	/**
	 * 根据url查询资源
	 * @param 
	 * @return
	 */
	public List<Resource> listByUrl(String url, Integer system) {
		List<Resource> result = resourceDao.listByUrlAndSystem(url, system);
		return result;
	}
	
	/**
	 * 根据url查询资源
	 * @param 
	 * @return
	 */
	public List<Long> listIdByUrl(String url, Integer system) {
		List<Resource> list = listByUrl(url, system);
		List<Long> result = new ArrayList<Long>();
		list.stream().forEach(new Consumer<Resource>() {

			@Override
			public void accept(Resource t) {
				Long l = t.getResourceId();
				result.add(l);
			}
		});
		return result;
	}
	
	public List<Resource> listNotIdByUrl(String url, Long resourceId, Integer system) {
		List<Resource> result = new ArrayList<Resource>();
		List<Resource> list = listByUrl(url, system);
		for (Resource c : list) {
			if (!c.getResourceId().equals(resourceId)) {
				result.add(c);
				break;
			}
		}
		return result;
	}
	
	/**
	 * 转换菜单资源混合树
	 * @param menuList
	 * @param result
	 */
	private void transferResourceTree(List<Resource> menuList,
			List<ListResourceTreeVo> result) {
		List<ListMenuTreeVo> tree = new ArrayList<>();
		transferTree(menuList, tree);
		to(tree, result);
	}
	
	/**
	 * 递归转换
	 * @param tree
	 * @param result
	 * @return
	 */
	private List<ListResourceTreeVo> to(List<ListMenuTreeVo> tree, List<ListResourceTreeVo> result) {
		if (result == null) {
			result = new ArrayList<>();
		}
		for (ListMenuTreeVo m : tree) {
			ListResourceTreeVo r = new ListResourceTreeVo();
			r.setId(m.getValue());
			r.setLabel(m.getLabel());
			r.setChildren(to(m.getChildren(), r.getChildren()));
			result.add(r);
		}
		return result;
		
	}
	

}
